TailsNS.ScriptManager = {

  getScriptLocator: function() {
    return {
      scripts: null,
      find: function(namespace, name) {
        namespace = namespace.toLowerCase();
        name = name.toLowerCase();

        for (var i = 0, script = null; (script = this.scripts[i]); i++) {
          if (script.namespace.toLowerCase() == namespace && script.name.toLowerCase() == name) {
            return i;
          }
        }

        return -1;
      },
      initFilename: function(script) {
        var index = {};
        var base = script.name.replace(/[^A-Z0-9_]/gi, "").toLowerCase();

        // If no Latin characters found - use default
        if (!base) {
          base = "tails_script";
        }

        // 24 is a totally arbitrary max length
        if (base.length > 24) {
          base = base.substring(0, 24);
        }
    
        for (var i = 0; i < this.scripts.length; i++) {
          index[this.scripts[i].filename] = this.scripts[i];
        }
    
        if (!index[base + ".tails.js"]) {
          script.filename = base + ".tails.js";
          return;
        }
    
        for (var count = 1; count < Number.MAX_VALUE; count++) {
          if (!index[base + count + ".tails.js"]) {
            script.filename = base + count + ".tails.js";
            return;
          }
        }
    
        throw new Error("doooooooode. get some different tails script or something.");
      },
      load: function() {
        var configContents = TailsNS.getContents(TailsNS.ScriptManager.getScriptFileURI("config.xml"));
        var doc = TailsNS.parseDOM(configContents, "text/xml");

        var nodes = doc.evaluate("/TailsScriptConfig/Script", doc, null, 0, null);

        this.scripts = [];

        for (var node = null; (node = nodes.iterateNext()); ) {
          var script = new TailsScript();
    
          for (var i = 0, childNode = null; (childNode = node.childNodes[i]); i++) {
            if (childNode.nodeName == "Include") {
              script.includes.push(childNode.firstChild.nodeValue);
            }
          }
    
          script.filename = node.getAttribute("filename");
          script.name = node.getAttribute("name");
          script.namespace = node.getAttribute("namespace");
          script.description = node.getAttribute("description");
          script.enabled = node.getAttribute("enabled") == true.toString();
  
          this.scripts.push(script);
        }
      },
      save: function() {
        var doc = document.implementation.createDocument("", "TailsScriptConfig", null);
    
        for (var i = 0, scriptObj = null; (scriptObj = this.scripts[i]); i++) {
          var scriptNode = doc.createElement("Script");

          for (var j = 0; j < scriptObj.includes.length; j++) {
            var includeNode = doc.createElement("Include");
            includeNode.appendChild(doc.createTextNode(scriptObj.includes[j]));
            scriptNode.appendChild(doc.createTextNode("\n\t\t"));
            scriptNode.appendChild(includeNode);
          }

          scriptNode.appendChild(doc.createTextNode("\n\t"));

          scriptNode.setAttribute("filename", scriptObj.filename);
          scriptNode.setAttribute("name", scriptObj.name);
          scriptNode.setAttribute("namespace", scriptObj.namespace);
          scriptNode.setAttribute("description", scriptObj.description);
          scriptNode.setAttribute("enabled", scriptObj.enabled);

          doc.firstChild.appendChild(doc.createTextNode("\n\t"));
          doc.firstChild.appendChild(scriptNode);
        }

        doc.firstChild.appendChild(doc.createTextNode("\n"))

        var configStream = TailsNS.getWriteStream(TailsNS.ScriptManager.getScriptFile("config.xml"));
        new XMLSerializer().serializeToStream(doc, configStream, "utf-8");
        configStream.close();
      }
    };
  },


  getActions: function(object, scriptErrors) {
    var scripts = this._getScriptsForObject(object);
    var actions = [];
    
    var errors = scriptErrors || [];
    for (var i=0; i<scripts.length; i++) {
      try {
        var action = eval("(function(){\n return {"
            + TailsNS.getContents(TailsNS.ScriptManager.getScriptFileURI(scripts[i].filename))
            + "};\n})()");
        action.object = object;
        action.sourceURL = object.source.url;
        action.label = scripts[i].name;
        action.__name = scripts[i].name;
        if (!action.getLabel) {
          action.getLabel = function() {return this.label};
        }
        actions.push(action);
      } catch(err) {
        var repeatedError = false;
        for (var j=0; j<errors.length; j++) {
          if (errors[j] == err.description) {
            repeatedError = true;
            break;
          }
        }
        if (!repeatedError) {
          errors.push(err.description);
          var msg = "Script error at " + scripts[i].name
            + "(" + (err.lineNumber-122) + "):\n\n"
            + err;
          alert(msg);
        }
      }
    }
    return actions;
  },
  _getScriptsForObject: function(object) {
    var scriptLocator = TailsNS.ScriptManager.getScriptLocator();
    var scripts = [];
    scriptLocator.load();
 
    for (var i = 0; i < scriptLocator.scripts.length; i++) {
      var script = scriptLocator.scripts[i];
      if (script.enabled) {
        for (var j = 0; j < script.includes.length; j++) {
          if (object.__name == script.includes[j]) {
            scripts.push(script);
          }
        }
      }
    }
    return scripts;
  },

  

  getScriptFileURI: function(fileName) {
    return TailsNS.getURI(this.getScriptFile(fileName));
  },
  getScriptFile: function(fileName) {
    var file = this.getScriptDir();
    file.append(fileName);
    return file;
  },
  getScriptDir: function() {
    var file = Components.classes["@mozilla.org/file/directory_service;1"]
        .getService(Components.interfaces.nsIProperties)
        .get("ProfD", Components.interfaces.nsILocalFile);
    file.append("tails_scripts");
    return file;
  },
  parseScriptName: function(sourceUri) {
    var name = sourceUri.spec;
    name = name.substring(0, name.indexOf(".tails.js"));
    name = name.substring(name.lastIndexOf("/") + 1);
    return name;
  },

  end: null
};

function TailsScript() {
  this.filename = null;
  this.name = null;
  this.namespace = null;
  this.description = null;
  this.enabled = true;
  this.includes = [];
}

var scriptDir = TailsNS.ScriptManager.getScriptDir();
if (!scriptDir.exists()) {
  scriptDir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0755);

  var defaultConfigFile = TailsNS.getContentDir();
  defaultConfigFile.append("default-config.xml");

  defaultConfigFile.copyTo(scriptDir, "config.xml");
  defaultConfigFile.permissions = 0644;
}

